from rest_framework.serializers import ModelSerializer  # 序列化器
from .models import *  # 导入所有的模型类
from django.contrib.auth.models import User  # auth自带的用户表
from rest_framework import serializers
from rest_framework.fields import SerializerMethodField  # 自定义数据格式模块
from datetime import datetime
from decimal import Decimal
from random import randint
from users.models import Address
from django.db import transaction  # 事务


# 商品分类序列化器 二级
class ClassificationSerializer(ModelSerializer):  # 序列化器类
    class Meta:
        model = Classification  # 转序列化器
        fields = ['id', 'name']


# 商品分类序列化器一级,包含子类
class ParentClassificationSerializer(ModelSerializer):  # 序列化器类
    classification_set = ClassificationSerializer(many=True, read_only=True)

    class Meta:
        model = Classification  # 转序列化器
        fields = ['id', 'name', 'classification_set', 'parent']

        extra_kwargs = {
            'parent': {'write_only': True},
        }


# 商品图片
class CommodityImgSerializer(ModelSerializer):  # 序列化器类
    class Meta:
        model = CommodityImg  # 转序列化器
        fields = ['src']  # 图片地址


# 商品序列化器
class CommoditySerializer(ModelSerializer):  # 序列化器类
    # 分类等级
    classification1_name = serializers.CharField(source='classification1.name', read_only=True)
    classification2_name = serializers.CharField(source='classification2.name', read_only=True)
    # 商品图
    commodityimg_set = CommodityImgSerializer(many=True, read_only=True)

    class Meta:
        model = Commodity  # 转序列化器
        exclude = ['is_delete']


# 购物车序列化器
class ShoppingCartSerializer(ModelSerializer):  # 序列化器类
    # 自定义一个字段,将商品嵌套在购物车当中
    commodityDetail = SerializerMethodField()

    class Meta:
        model = ShoppingCart  # 转序列化器
        fields = '__all__'  # 映射展示所有字段

    # 对象级别校验
    def validate(self, data):  # data 字典
        if data['number'] <= 0:
            raise serializers.ValidationError('购买的商品数量错误')
        elif data['number'] > data['commodity'].stock:
            raise serializers.ValidationError('商品超出库存')
        else:
            return data

    def get_commodityDetail(self, shoppingcart):
        return CommoditySerializer(shoppingcart.commodity).data


# 订单序列化器
class OrderSerializer(ModelSerializer):  # 序列化器类
    # 用于接收传入的要结算的商品id
    cart = serializers.ListField(write_only=True)  # 列表

    class Meta:
        model = Order  # 转序列化器
        fields = '__all__'  # 映射展示所有字段
        read_only_fields = ['order_id','total_count','total_amount','status','user']

    def create(self, validated_data):  # 自定义序列化器中创建的方法
        user = self.context['request'].user  # 获取用户
        # 订单号日期+时间+六位数的用户id+随机两位数字
        order_id = datetime.now().strftime('%Y%m%d%H%M%S')+'%06d%02d'%(user.id,randint(1,99))

        # 获取前端传入的订单支付方式
        pay_method = validated_data.get('pay_method')
        try:
            address = Address.objects.get(id=validated_data.get('address'))
        except Address.DoesNotExist:
            raise serializers.ValidationError('address error')
        # 订单提交后的收货地址
        address_s = f'{address.province.name} {address.city.name} {address.district.name} {address.place} [{address.receiver} 收] {address.mobile}'
        # 上下文做事务处理
        with transaction.atomic():
            # 创建保存点
            save_point = transaction.savepoint()
            try:
                # 创建的订单信息
                order = Order.objects.create(
                    order_id=order_id,  # 订单id
                    total_count=0,  # 商品数
                    total_amount = Decimal('0.00'),  # 商品金额
                    pay_method=pay_method,  # 支付方式
                    status = 1 if pay_method==1 else 2,  # 状态
                    user = user,  # 用户
                    address=address_s # 收货地址
                )

                # 获取购物车当中要结算的商品
                carts = validated_data.get('cart')  # 列表
                for cart_id in carts:
                    while True:
                        try:
                            cart = ShoppingCart.objects.get(id=cart_id)  # 购物车对象
                        except ShoppingCart.DoesNotExist:
                            # 回滚
                            transaction.savepoint_rollback(save_point)
                            raise serializers.ValidationError('购物信息不存在')

                        commodity = cart.commodity  # 商品

                        # 原本仓库的库存及销量获取到
                        origin_stock = commodity.stock  # 库存
                        origin_sales = commodity.sales  # 销量

                        # 核算
                        if cart.number > origin_stock:
                            raise serializers.ValidationError('库存不足')

                        # 减少库存，增加销量
                        new_stock = origin_stock - cart.number
                        new_sales = origin_sales + cart.number

                        # 更新商品数据
                        res = Commodity.objects.filter(id=commodity.id,stock=origin_stock).update(stock=new_stock,sales=new_sales)
                        if not res:
                            continue
                        # 创建商品订单对应的订单详情数据
                        OrderGoods.objects.create(
                            number=cart.number,
                            price=commodity.price,
                            order=order,
                            commodity=commodity
                        )

                        # 更新订单表数据
                        # 订单数量
                        order.total_count+=cart.number
                        # 订单金额
                        order.total_amount+=(cart.number*commodity.price)

                        break
                # 保存订单信息
                order.save()

                # 结算后需要删除购物车当中的商品对象
                ShoppingCart.objects.filter(id__in=carts).delete()
            except Exception as e:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError(e)
            else:
                # 提交
                transaction.savepoint_commit(save_point)

        return order



# 支付凭证序列化器
class PaymentSerializer(ModelSerializer):  # 序列化器类
    class Meta:
        model = Payment  # 转序列化器
        fields = '__all__'  # 映射展示所有字段




